package other.edan.system.k3;


import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.data.model.*;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.OperateResult;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.edan.system.client.EdanK3Utils;
import other.edan.system.utils.*;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description 同步K3销售出库数据
 * @Author 黎炎松
 * 2024-08-30 10:20
 */
@RestApi(baseUrl = "/xsy/salesOut")
public class SyncSalesOut extends SyncSuper implements ScheduleJob, FutureTask {
    private static XoqlService xoqlService = XoqlService.instance();
    private static final Logger logger = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "同步K3销售出库数据 ==> ";

    // 执行定时任务
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        logger.debug(LOGGER_MSG + " 执行定时任务开始");
        try {
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
            logger.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            logger.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    // 执行异步函数
    @Override
    public void execute(String s) throws ScriptBusinessException {
        startSyncSalesOut("");
    }

    /**
     * 根据产品编号手动触发产品同步
     * @param
     * @return
     */
    @RestMapping(value = "/syncById", method = RequestMethod.POST)
    public String syncById(@RestQueryParam(name = "id") Long outId, @RestQueryParam(name = "fbillNo") String fbillNo) {

        logger.debug("根据编号手动触发同步: fbillNo " + fbillNo);
        if (StringUtils.isNotBlank(fbillNo)) {
            return startSyncSalesOut(fbillNo);
        }

        // 获取产品的编码
        logger.debug("根据出库编号手动触发销售出库同步: " + outId);
        SalesOutReceipt__c salesOutReceipt = new SalesOutReceipt__c();
        salesOutReceipt.setId(outId);
        salesOutReceipt = HCXObjectService.get(salesOutReceipt);
        String outNo = salesOutReceipt.getName();

        logger.debug("根据出库编号手动触发销售出库同步: " + outNo);
        return startSyncSalesOut(outNo);
    }

    /**
     * 手动触发产品同步
     * @param
     * @return
     */
    @RestMapping(value = "/handerSync", method = RequestMethod.POST)
    public String handerSync() throws AsyncTaskException {
        logger.debug("手动触发出库同步");
        String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
        logger.info(LOGGER_MSG + "异步ID:" + messageId);
        return TfReturnMsgTools.getSuccessResult("Start synchronizing data");
    }


    public static void main(String[] args) throws ApiEntityServiceException {
        HCXObjectService.isLocal = true;
        new SyncSalesOut().startSyncSalesOut("XOUT456298");
    }

    /**
     * 开始同步产品数据
     */
    public String startSyncSalesOut(String salesOutNo) {
        try {
            logger.debug(LOGGER_MSG + "处理开始");

            // 从数据配置表中获取数据
            String sql = "select id,lastSyncTime__c,syncAssistVal__c from syncConfig__c where syncKey__c = 'K3_XXCK'";
            SyncConfig__c syncConfig = HCXObjectService.queryOne(sql);
            logger.debug(LOGGER_MSG + " syncConfig = " + syncConfig);
            if (syncConfig == null) {
                logger.debug(LOGGER_MSG + " 数据配置信息不存在");
                return TfReturnMsgTools.getFailResult("Data configuration information does not exist");
            }

            // 获取同步时间
            String startDate = syncConfig.getLastSyncTime__c();
            String endDate = HCDateUtils.dateToString(new Date(), HCDateUtils.FORMATTIME); // 同步结束时间
            if (StringUtils.isBlank(startDate)) {
                // 如果为空则退回1天前
                startDate = HCDateUtils.getDaysBeforeString(1, HCDateUtils.FORMATTIME);
            }

            // 设置参数
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("page", "1");
            paramsMap.put("pageSize", "3000");
            // 销售订单号如果不为空 则只查询单条数据
            if (StringUtils.isNotBlank(salesOutNo)) {
                paramsMap.put("icstockbillNo", salesOutNo);
            } else {
                // todo
                startDate = "2022-01-20 00:00:00";
                endDate = "2024-08-30 00:00:00";
                paramsMap.put("StartDate", startDate);
                paramsMap.put("EndDate", endDate);
            }
            logger.debug(LOGGER_MSG + " paramsMap: " + paramsMap);

            // 发送请求获取数据
            ResultBody response = EdanK3Utils.sendGet(paramsMap, EdanK3Utils.GET_SALES_OUT_URL, "");
            if (!Objects.equals(response.getCode(), "200")) {
                logger.debug(LOGGER_MSG + "查询k3销售出库数据异常: " + response.getMessage());
                return TfReturnMsgTools.getFailResult("Abnormal query of k3 sales outbound data: " + response.getMessage());
            }

            // 获取数据 判断是否有值
            JSONObject result = (JSONObject) response.getResult();
            List<JSONObject> salOutList = JSONObject.parseArray(result.getJSONArray("ICStockInfos").toJSONString(), JSONObject.class);
            logger.debug(LOGGER_MSG + "查询返回的数据: " + salOutList.size());
            if (salOutList.size() <= 0) {
                logger.debug(LOGGER_MSG + "暂无需要处理的数据");
                // 同步修改配置表
                upSysConfig(syncConfig, endDate, 0);
                return TfReturnMsgTools.getSuccessResult("There is no data that needs to be synchronized");
            }

            // 获取选项集
            JSONObject salesOutDesc = ComUtils.getEntityDesc("salesOutReceipt__c");
            Map<String, String> salesBusinessOpt = ComUtils.getMapsFromDescribeJson(salesOutDesc, "salesBusinessType__c", false); // 销售业务类型

            // 获取查询的参数
            Set<String> fbillNoSet = new HashSet<>();
            Set<String> primaryKeySet = new HashSet<>();
            Set<String> prdNumberSet = new HashSet<>();
            Set<String> orderNoSet = new HashSet<>();
            Set<String> accountSet = new HashSet<>();
            for (JSONObject salOut : salOutList) {
                fbillNoSet.add("'" + salOut.getString("fbillNo") + "'"); // 出库编码
                primaryKeySet.add("'" + salOut.getString("finterID") + salOut.getString("fentryID") + "'"); // 订单明细key
                prdNumberSet.add("'" + salOut.getString("fnumber") + "'"); // 产品编码
                orderNoSet.add("'" + salOut.getString("seOrderNo") + "'"); // 销售订单
                accountSet.add("'" + salOut.getString("customerCode") + "'"); // 客户
            }

            // 按照订单号进行分组
            Map<String, List<JSONObject>> salOutListMap = salOutList.stream().collect(Collectors.groupingBy(e -> e.getString("fbillNo")));
            logger.debug(LOGGER_MSG + "salOutListMap: " + salOutListMap);

            // 获取系统中存在的销售出库
            String fbillNos = StringUtils.join(fbillNoSet, ",");
            sql = "select id,name from salesOutReceipt__c where name in (" + fbillNos + ")";
            Map<String, Long> crmSalOutMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e -> e.getString("name"), e1 -> e1.getLong("id")));
            logger.debug(LOGGER_MSG + "crmSalOutMap: " + crmSalOutMap);

            // 获取系统中存在的销售出库明细 fbillNo + "_" + fentryID
            String primaryKeys = StringUtils.join(primaryKeySet, ",");
            sql = "select id,edanId__c from salesOutboundDetails__c where edanId__c in (" + primaryKeys + ")";
            Map<String, Long> crmOutDetailMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e -> e.getString("edanId__c"), e1 -> e1.getLong("id")));
            logger.debug(LOGGER_MSG + "crmOutDetailMap: " + crmOutDetailMap);

            // 获取系统中的产品
            String prdNumbers = StringUtils.join(prdNumberSet, ",");
            sql = String.format("select id,FNumber__c from product where FNumber__c in (%s)", prdNumbers);
            Map<String, Long> prdNumberMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("FNumber__c"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "prdNumberMap: " + prdNumberMap);

            // 获取系统中的销售订单
            String orderNos = StringUtils.join(orderNoSet, ",");
            sql = String.format("select id,name from salesOrder__c where name in (%s)", orderNos);
            Map<String, Long> orderMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("name"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "orderMap: " + orderMap);

            // 获取系统中的客户
            String accounts = StringUtils.join(accountSet, ",");
            sql = String.format("select id,customerCodeNumber__c from account where customerCodeNumber__c in (%s)", accounts);
            Map<String, Long> accountMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("customerCodeNumber__c"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "accountMap: " + accountMap);


            // 获取新增、修改的数据
            List<SalesOutReceipt__c> upOutList = new ArrayList<>(); // 修改出库
            List<SalesOutboundDetails__c> upOutDetailList = new ArrayList<>(); // 修改出库详情
            for (String fbillNo : salOutListMap.keySet()) {
                // 明细数据
                List<JSONObject> outDetailList = salOutListMap.get(fbillNo);
                if (outDetailList.size() <= 0) {
                    continue;
                }

                // 处理出库
                JSONObject outObject = outDetailList.get(0); // 出库数据
                String finterID = outObject.getString("finterID");
                SalesOutReceipt__c salesOutReceipt = new SalesOutReceipt__c();
                salesOutReceipt.setEntityType(3423063823276583L);
                salesOutReceipt.setEdanId__c(finterID); // k3数据id
                salesOutReceipt.setName(fbillNo); // 编号
                salesOutReceipt.setDepartment__c(outObject.getString("department")); // 部门 department
                salesOutReceipt.setSalesBusinessType__c(ComUtils.getOptVal(salesBusinessOpt, outObject.getString("marketingStyle"))); // 销售业务类型 marketingStyle
                salesOutReceipt.setContractCode__c(outObject.getString("contractNumber")); // 正式合同编码
                salesOutReceipt.setDate__c(getDateVal(outObject.getString("fdate"))); // 日期
                salesOutReceipt.setAbstract__c(outObject.getString("explanation")); // 摘要
                salesOutReceipt.setCustomer__c(accountMap.get(outObject.getString("customerCode"))); // 购货单位 customer
                salesOutReceipt.setDeliveryAddress__c(outObject.getString("address")); // 收货地址
                salesOutReceipt.setConsignee__c(outObject.getString("consignee")); // 收货人
                salesOutReceipt.setReceivingTelephone__c(outObject.getString("tel")); // 收货电话
                salesOutReceipt.setSalesOrder__c(orderMap.get(outObject.getString("seOrderNo"))); // 订单号
                salesOutReceipt.setAccessoriesPackaging__c(outObject.getString("packageNote")); // 包装信息
                salesOutReceipt.setCollectionDate__c(DateTools.stringToLong(outObject.getString("payDate"), "yyyy-MM-dd HH:mm:ss.S")); // 收款日期

                // 判断系统中是否存在，存在则更新
                logger.debug(LOGGER_MSG + "salesOutReceipt = " + salesOutReceipt);
                if (crmSalOutMap.containsKey(fbillNo)) {
                    salesOutReceipt.setId(crmSalOutMap.get(fbillNo));
                    upOutList.add(salesOutReceipt);
                    // 进行更新
                    if (upOutList.size() >= 100) {
                        HCXObjectService.updateBatch(upOutList);
                        upOutList.clear();
                    }
                } else {
                    // 新增
                    OperateResult insert = HCXObjectService.insert(salesOutReceipt);
                    if (!insert.getSuccess()) {
                        logger.error(LOGGER_MSG + "新增出库失败 fbillNo: " + fbillNo);
                        continue;
                    }
                    salesOutReceipt.setId(insert.getDataId());
                }

                // 处理出库明细数据 (不考虑k3后续同步删除订单明细的情况)
                for (JSONObject outDetailObj : outDetailList) {
                    List<SalesOutboundDetails__c> addOutDetail = new ArrayList<>(); // 新增出库详情

                    // 明细对象
                    String fentryID = outDetailObj.getString("fentryID");
                    String edanId = finterID + fentryID; // 唯一标识: finterID + fentryID

                    SalesOutboundDetails__c salesOutDetails = new SalesOutboundDetails__c();
                    salesOutDetails.setEntityType(3423103933307337L);
                    salesOutDetails.setSalesOutReceipt__c(salesOutReceipt.getId()); // 主表
                    salesOutDetails.setEdanId__c(edanId);// 唯一标识:
                    salesOutDetails.setName(fentryID); // 编号
                    salesOutDetails.setProductCode__c(prdNumberMap.get(outDetailObj.getString("fnumber"))); // 产品
                    salesOutDetails.setInvoiceDatabase__c(outDetailObj.getString("ffpkNumber")); // 发票库对应码
                    salesOutDetails.setBatchNo__c(outDetailObj.getString("batchNo")); // 批号
                    salesOutDetails.setQuantity__c(outDetailObj.getDouble("fqty")); // 数量
                    salesOutDetails.setQuantityDelivered__c(outDetailObj.getDouble("fqtyMust")); // 应发数量
                    salesOutDetails.setActualQuantity__c(outDetailObj.getDouble("fqtyActual")); // 实发数量
                    salesOutDetails.setRemark__c(outDetailObj.getString("fnote")); // 备注
                    salesOutDetails.setModelCategory__c(outDetailObj.getString("model")); // 机型类别
                    salesOutDetails.setAttribute("FOwnerName__c", outDetailObj.getString("fownerName")); // 所属机型
                    salesOutDetails.setSubordinateSalesman__c(outDetailObj.getString("salor")); // 所属业务员
                    salesOutDetails.setAttribute("finalCountry__c", outDetailObj.getString("finalCountry")); // 国家

                    // 判断是新增还是修改
                    if (crmOutDetailMap.containsKey(edanId)) {
                        salesOutDetails.setId(crmOutDetailMap.get(edanId));
                        upOutDetailList.add(salesOutDetails);
                    } else {
                        addOutDetail.add(salesOutDetails);
                    }

                    // 进行新增、编辑操作
                    HCXObjectService.insertBatch(addOutDetail);
                    if (upOutDetailList.size() > 100) {
                        HCXObjectService.updateBatch(upOutDetailList);
                        upOutDetailList.clear();
                    }
                }
            }

            // 进行批量、新增更新
            HCXObjectService.updateBatch(upOutList);
            HCXObjectService.updateBatch(upOutDetailList);

            // 更新同步配置
            if (StringUtils.isBlank(salesOutNo)) {
                upSysConfig(syncConfig, endDate, salOutListMap.size());
            }

            logger.debug(LOGGER_MSG + "处理成功");
            return TfReturnMsgTools.getSuccessResult("Synchronization successful");
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(LOGGER_MSG + "处理异常:" + e.getMessage());
            return TfReturnMsgTools.getFailResult("Synchronization exception:" + e.getMessage());
        }
    }


}
